package com.baizhi.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

/**
 * 自定义切面配置类
 */
@Configuration
@Aspect
public class MyAspectConfig {

    private static final Logger log = LoggerFactory.getLogger(MyAspectConfig.class);

    //切入点表达式:
    // 1.execution 方法级别切入点表达式 save update 运行效率越低
    // 2.within:类级别切入点表达式: 控制越粗 运行效率
    // 3.基于注解的切入点表达式 @annotation(com.baizhi.annotations.xxx)

    //@Around("execution(* com.baizhi.service.*.*(..))")
    //@Around("within(com.baizhi.service.*)")

    /**
     * 在整个controller包下使用环绕通知
     *
     * 打印当前执行类
     * 打印方法名
     * 执行目标方法
     * 返回目标方法的返回值
     */
    // 返回值作用: 用来讲业务方法返回结果返回给调用者
    @Around(value = "within(com.baizhi.controller.*)")
    public Object around(ProceedingJoinPoint pjp){
        log.info("环绕前置： {}方法的入参：{}",pjp.getSignature().getName(), Arrays.toString(pjp.getArgs()));
        Object result = null;
        try {
            result = pjp.proceed();
            log.info("环绕正常返回的结果：{}",result);
        } catch (Throwable throwable) {
            log.error("环绕异常信息：{}", throwable.getMessage());
        } finally {
            log.info("环绕后置通知在finally，最终一定会执行");
        }
        return result;
    }

    /**
     * 只作用于userController类中的所有方法
     * 利用环绕前置打印方法的参数
     */
    @Before(value = "target(com.baizhi.controller.UserController)")
    public void before(JoinPoint jp){
        log.info("【前置通知】- {}方法的入参：{}",jp.getSignature().getName(), Arrays.toString(jp.getArgs()));
    }


    /**
     * 只在service的某个方法打印日志
     * 利用后置通知随便打印一句话（在返回通知前，执行方法后，这期间执行）
     */
    @After(value = "execution(public * com.baizhi.service.UserServiceImpl.*(..))")
    public void after(JoinPoint jp){
        log.info("【后置通知】- {}方法的入参：{}",jp.getSignature().getName(), Arrays.toString(jp.getArgs()));
    }

    /**
     * 只打印带有@myAdvice的方法
     * 利用返回通知打印方法的返回值
     */
    @AfterReturning(value = "@annotation(com.baizhi.annotations.MyAdvice)",returning = "result")
    public void afterReturning(JoinPoint jp,Object result){
        log.info("【返回通知】- {}方法的入参：{}",jp.getSignature().getName(), Arrays.toString(jp.getArgs()));
        log.info("【返回通知】- {}方法的返回值：{}",jp.getSignature().getName(),result);
    }






}
